using AutoMapper;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Work.API.Applications.Write.Commands;
using Work.Domain.DrugManage;
using Work.ErrorCode;
using Work.Infrastructure.Interfaces;

namespace Work.API.Applications.Write.CommandHandlers
{
    /// <summary>
    /// 药品出库处理器（用于药品出库模块）
    /// 业务逻辑：
    /// 1. 验证药品是否存在
    /// 2. 验证库存是否充足
    /// 3. 扣除库存数量
    /// 4. 创建出库记录
    /// 5. 可选：更新检药单的已发药状态
    /// </summary>
    public class OutboundDrugCommandHandler : IRequestHandler<OutboundDrugCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<Drug> _drugRepo;
        private readonly IBaseRepository<DrugOutbound> _outboundRepo;
        private readonly IBaseRepository<DrugInspection> _inspectionRepo;
        private readonly IMapper _mapper;

        public OutboundDrugCommandHandler(
            IBaseRepository<Drug> drugRepo,
            IBaseRepository<DrugOutbound> outboundRepo,
            IBaseRepository<DrugInspection> inspectionRepo,
            IMapper mapper)
        {
            _drugRepo = drugRepo;
            _outboundRepo = outboundRepo;
            _inspectionRepo = inspectionRepo;
            _mapper = mapper;
        }

        public async Task<ApiResult<int>> Handle(OutboundDrugCommand request, CancellationToken cancellationToken)
        {
            var result = new ApiResult<int>();

            try
            {
                // 1. 验证药品是否存在
                var drug = await _drugRepo.GetById(request.DrugId);
                if (drug == null || !drug.IsEnabled)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "药品不存在或已禁用";
                    result.Data = 0;
                    return result;
                }

                // 2. 验证库存是否充足
                if (drug.Inventory < request.Quantity)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = $"库存不足，当前库存：{drug.Inventory}，需要数量：{request.Quantity}";
                    result.Data = 0;
                    return result;
                }

                // 3. 扣除库存数量
                drug.Inventory -= request.Quantity;
                drug.UpdateTime = DateTime.Now;
                drug.UpdateBy = request.Operator;

                var drugRows = await _drugRepo.UpdateAsync(drug);

                if (drugRows <= 0)
                {
                    result.Code = ApiEnum.失败;
                    result.Message = "库存更新失败";
                    result.Data = 0;
                    return result;
                }

                // 4. 创建出库记录
                var outbound = new DrugOutbound
                {
                    DrugId = request.DrugId,
                    PrescriptionItemId = request.PrescriptionItemId,
                    AppointmentId = request.AppointmentId,
                    PatientId = request.PatientId,
                    CardNumber = request.CardNumber,
                    RegistrationNum = request.RegistrationNum,
                    PatientName = request.PatientName,
                    Quantity = request.Quantity,
                    UnitPrice = request.UnitPrice,
                    TotalAmount = request.UnitPrice * request.Quantity,
                    OutboundDate = DateTime.Now,
                    Operator = request.Operator,
                    Remarks = request.Remarks,
                    CreateTime = DateTime.Now
                };

                var outboundRows = await _outboundRepo.AddAsync(outbound);

                if (outboundRows <= 0)
                {
                    // 如果出库记录创建失败，需要回滚库存
                    drug.Inventory += request.Quantity;
                    await _drugRepo.UpdateAsync(drug);

                    result.Code = ApiEnum.失败;
                    result.Message = "出库记录创建失败，已回滚库存";
                    result.Data = 0;
                    return result;
                }

                // 5. 可选：如果有关联的检药单，更新检药单的已发药状态
                if (request.PrescriptionItemId.HasValue)
                {
                    var inspection = await _inspectionRepo.GetAll()
                        .FirstOrDefaultAsync(x => x.PrescriptionItemId == request.PrescriptionItemId.Value);

                    if (inspection != null)
                    {
                        inspection.IsDispensed = true;
                        inspection.DispensedDate = DateTime.Now;
                        inspection.InspectionStatus = "已发药";
                        await _inspectionRepo.UpdateAsync(inspection);
                    }
                }

                result.Code = ApiEnum.成功;
                result.Message = "药品出库成功";
                result.Data = outbound.OutboundId;
            }
            catch (Exception ex)
            {
                result.Code = ApiEnum.失败;
                result.Message = $"出库失败：{ex.Message}";
                result.Data = 0;
            }

            return result;
        }
    }
}

